unit TMDemoForm;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  NotifyDef,TimerDef,TMImport, ExtCtrls, StdCtrls, Buttons;

const
  WM_TIMERNOTIFY = WM_USER+100;
  WM_ASYNCNOTIFY = WM_USER+101;

type
  TfmDemo = class(TForm)
    StartButton: TSpeedButton;
    StopButton: TSpeedButton;
    ResetButton: TSpeedButton;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    TimerView1: TStaticText;
    TimerView2: TStaticText;
    TimerView3: TStaticText;
    IntervalEdit: TEdit;
    Label4: TLabel;
    VCLTimer: TTimer;
    LogMemo: TMemo;
    TimerView0: TStaticText;
    Label5: TLabel;
    PrioSwitch: TRadioGroup;
    AutoStopEdit: TEdit;
    Label6: TLabel;
    TimerView4: TStaticText;
    Label7: TLabel;
    GroupBox1: TGroupBox;
    UserButton: TSpeedButton;
    SleepEdit: TEdit;
    Label8: TLabel;
    Label9: TLabel;
    CronEdit: TComboBox;
    procedure FormCreate(Sender: TObject);
    procedure StartButtonClick(Sender: TObject);
    procedure StopButtonClick(Sender: TObject);
    procedure ResetButtonClick(Sender: TObject);
    procedure VCLTimerTimer(Sender: TObject);
    procedure UserButtonClick(Sender: TObject);
    procedure PrioSwitchClick(Sender: TObject);
  private
    { Private declarations }
    MSecOrg,MSecCnt : integer;
    TimerCnt : array[1..4] of integer;
    TimerView : array[1..4] of TStaticText;
    hTimer2,hTimer3,hTimer4 : THandle;
    procedure WMTimerNotifyMsg(var Message : TMessage); message WM_TIMERNOTIFY;
    procedure WMAsyncNotify(var Message : TMessage); message WM_ASYNCNOTIFY;
    procedure TimerNotifyEvent(Sender : TObject; Msg,UserParam : dword);
    procedure TimerTick(Num: integer);
    procedure WriteLog(const S: string);
    procedure ShowTimer(Num: integer);
  public
    { Public declarations }
  end;

var
  fmDemo: TfmDemo;

implementation

{$R *.DFM}

procedure TfmDemo.FormCreate(Sender: TObject);
const HelloStr = 'Hello from Timer!';
begin
  TimerView[1] := TimerView1;
  TimerView[2] := TimerView2;
  TimerView[3] := TimerView3;
  TimerView[4] := TimerView4;
  hTimer2 := tmCreateIntervalTimerEx(Handle, 100, tmPeriod,
      false, tnWinMsg, WM_TIMERNOTIFY, 2);
  hTimer3 := tmCreateIntervalTimer(TimerNotifyEvent, 100, tmPeriod,
      false, dword(pchar(HelloStr)), 3);
  hTimer4 := tmCreateFixedTimer(TimerNotifyEvent, CronEdit.Text, tmSureSync,
      false, dword(pchar(HelloStr)), 4);
end;

procedure TfmDemo.StartButtonClick(Sender: TObject);
var I : integer;
begin
  i := strtoint(IntervalEdit.Text);
  MSecOrg := GetTickCount;
  VCLTimer.Interval := i;
  VCLTimer.Enabled := true;
  tmSetTimerInterval(hTimer2, i);
  tmStartTimer(hTimer2);
  tmSetTimerInterval(hTimer3, i);
  tmStartTimer(hTimer3);
  tmSetTimerMask(hTimer4, CronEdit.Text);
  tmStartTimer(hTimer4);
  WriteLog('Start timers');
end;

procedure TfmDemo.StopButtonClick(Sender: TObject);
begin
  VCLTimer.Enabled := false;
  tmStopTimer(hTimer2);
  tmStopTimer(hTimer3);
  tmStopTimer(hTimer4);
  WriteLog('Stop timers');
end;

procedure TfmDemo.ResetButtonClick(Sender: TObject);
begin
  MSecCnt := 0;
  fillchar(TimerCnt, sizeof(TimerCnt), 0);
  tmResetTimer(hTimer2);
  tmResetTimer(hTimer3);
  tmResetTimer(hTimer4);
  WriteLog('Reset timers');
end;

procedure TfmDemo.ShowTimer(Num : integer);
var S : string; T,Prev : Integer;
begin
  T := GetTickCount; Prev := MSecCnt;
  inc(MSecCnt, T-MSecOrg);
  MSecOrg := T;
  TimerView0.Caption := IntToStr(MSecCnt);
  S := IntToStr(TimerCnt[Num]);
  TimerView[Num].Caption := S;
  WriteLog(format('Timer %d Count=%s', [Num, S]));
  T := strtoint(AutostopEdit.Text);
  if (Prev < T) and (MSecCnt >= T) then StopButtonClick(nil);
end;

procedure TfmDemo.TimerTick(Num : integer);
begin
  inc(TimerCnt[Num]);
  ShowTimer(Num);
end;

procedure TfmDemo.WriteLog(const S : string);
begin
  LogMemo.Lines.Add(formatdatetime('hh:nn:ss.zzz', Time) + ' ' + S);
end;

procedure TfmDemo.VCLTimerTimer(Sender: TObject);
begin
  TimerTick(1);
end;

procedure TfmDemo.TimerNotifyEvent(Sender: TObject; Msg, UserParam: dword);
begin
  inc(TimerCnt[UserParam]);
  PostMessage(Handle, WM_ASYNCNOTIFY, UserParam, 0);
end;

procedure TfmDemo.WMTimerNotifyMsg(var Message: TMessage);
begin
  TimerTick(Message.WParam);
end;

procedure TfmDemo.WMAsyncNotify(var Message: TMessage);
begin
  ShowTimer(Message.WParam);
end;

procedure TfmDemo.UserButtonClick(Sender: TObject);
var Delay : integer;
begin
  Screen.Cursor := crHourGlass;
  Delay := strtoint(SleepEdit.Text);
  WriteLog(format('Sleep for %d msec', [Delay]));
  sleep(Delay);
  Screen.Cursor := crDefault;
end;

procedure TfmDemo.PrioSwitchClick(Sender: TObject);
var hProcess : THandle;
begin
  hProcess := GetCurrentProcess;
  case (Sender as TRadioGroup).ItemIndex of
    0 : SetPriorityClass(hProcess, REALTIME_PRIORITY_CLASS);
    1 : SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS);
    2 : SetPriorityClass(hProcess, NORMAL_PRIORITY_CLASS);
    3 : SetPriorityClass(hProcess, IDLE_PRIORITY_CLASS);
  end;
end;

end.
